{
 "metadata": {
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.0-final"
  },
  "orig_nbformat": 2,
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3.9.0 64-bit ('venv')",
   "metadata": {
    "interpreter": {
     "hash": "1ee744fdee3946c2af2bdc58f3796819357ed068616caa870dc20aacb53d0af6"
    }
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2,
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "execution_count": 2
    }
   ],
   "source": [
    "##数据库配置、连接、关闭-基本操作\n",
    "\n",
    "from peewee import *\n",
    "\n",
    "# SQLite database using WAL journal mode and 64MB cache.\n",
    "sqlite_db = SqliteDatabase('sqlite_db.db',   # 文件名（当前目录），路径（其他文件夹）\n",
    "                           pragmas={  # 各种配置\n",
    "                              'journal_mode': 'wal',\n",
    "                              'cache_size': -1024 * 64})\n",
    "sqlite_db.connect()\n",
    "sqlite_db.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "## SQLite的扩展 SqliteDatabase\n",
    "#                   --> SqliteExtDatabase \n",
    "#                       --> PooledSqliteExtDatabase    \n",
    "#                   --> PooledSqliteDatabase\n",
    "# 这4个都可以建立连接\n",
    "\n",
    "from playhouse.sqlite_ext import SqliteExtDatabase\n",
    "\n",
    "# Use SQLite (will register a REGEXP function and set busy timeout to 3s).\n",
    "db = SqliteExtDatabase('people.db',\n",
    "                       regexp_function=True,\n",
    "                       timeout = 4,\n",
    "                       pragmas = {\n",
    "                           'journal_mode': 'wal',\n",
    "                       } )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "db.pragma() 配置属性\n",
    "    - cache_size: -1 * 数据大小kb  \n",
    "    - journal_mode: \n",
    "        - wal\n",
    "    - foreign_keys:\n",
    "    - ignore_check_constrains：\n",
    "    - synchronous：  \n",
    "    - 以上是常用的\n",
    "\n",
    "# db.cache_size 调用属性 \n",
    "'''\n",
    "db.pragma('cache_size', -1024 *64) # permanent= True 强制持久化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "cache_size: -65536\nforeign_keys: 0\njournal_mode: wal\npage_size: 4096\n[]\n"
     ]
    }
   ],
   "source": [
    "print('cache_size:', db.cache_size)\n",
    "print('foreign_keys:', db.foreign_keys) \n",
    "print('journal_mode:', db.journal_mode)\n",
    "print('page_size:', db.page_size)\n",
    "print(db._table_functions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "db.pragma('foreign_keys', 0, permanent= True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "#用户自定义函数部分没有看懂，装饰器的用法也忘记了"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在程序运行时设置数据库的三种方法\n",
    "#1 \n",
    "db_1 = SqliteDatabase('my_app.db', pragmas = {'journal_mode':'wal'})\n",
    "\n",
    "#2\n",
    "db_2 = SqliteDatabase(None)\n",
    "\n",
    "db_2.init('de_filename.db', pragmas={'journal_mode':'wal'})\n",
    "\n",
    "#3\n",
    "db_3 = DatabaseProxy()\n",
    "\n",
    "db_3.initialize(db_1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "output_type": "error",
     "ename": "OperationalError",
     "evalue": "Connection already opened.",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mOperationalError\u001b[0m                          Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-24-4986046919b9>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mdb_1\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mconnect\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32me:\\worktools\\venv\\lib\\site-packages\\peewee.py\u001b[0m in \u001b[0;36mconnect\u001b[1;34m(self, reuse_if_open)\u001b[0m\n\u001b[0;32m   3067\u001b[0m                 \u001b[1;32mif\u001b[0m \u001b[0mreuse_if_open\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m   3068\u001b[0m                     \u001b[1;32mreturn\u001b[0m \u001b[1;32mFalse\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 3069\u001b[1;33m                 \u001b[1;32mraise\u001b[0m \u001b[0mOperationalError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Connection already opened.'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m   3070\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m   3071\u001b[0m             \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_state\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mreset\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mOperationalError\u001b[0m: Connection already opened."
     ]
    }
   ],
   "source": [
    "db_1.connect()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "execution_count": 25
    }
   ],
   "source": [
    "db_1.connect(reuse_if_open=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "execution_count": 27
    }
   ],
   "source": [
    "db_1.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "<bound method Database.is_closed of <peewee.SqliteDatabase object at 0x00000186F22BAB80>>"
      ]
     },
     "metadata": {},
     "execution_count": 28
    }
   ],
   "source": [
    "db_2.is_closed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "execution_count": 30
    }
   ],
   "source": [
    "db_2.connect(reuse_if_open=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "execution_count": 35
    }
   ],
   "source": [
    "db_2.is_closed()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "with db_2:\n",
    "    print(db.is_closed())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "execution_count": 32
    }
   ],
   "source": [
    "db_2.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "True\nFalse\n"
     ]
    }
   ],
   "source": [
    "with db_1.connection_context():\n",
    "    print(db_1.is_connection_usable())\n",
    "    print(db_1.is_closed())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 等下认真学习下装饰器的玩法，这里基本都在用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "from playhouse.pool import PooledSqliteDatabase\n",
    "\n",
    "db = PooledSqliteDatabase(\n",
    "    'my_app.db', \n",
    "    max_connections= 30, # 最大连接数\n",
    "    stale_timeout= 300, # 过期时间\n",
    "    pragmas = {  # 其他参数\n",
    "        'journal_mode': 'wal'\n",
    "    })\n",
    "\n",
    "class BaseModel(Model):\n",
    "    class Meta:\n",
    "        database = db"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "import unittest\n",
    "from peewee import *\n",
    "\n",
    "test_db = SqliteDatabase(':memory:')\n",
    "\n",
    "class User(BaseModel):\n",
    "    pass\n",
    "\n",
    "class Tweet(BaseModel):\n",
    "    pass\n",
    "\n",
    "class EventLog(BaseModel):\n",
    "    pass\n",
    "\n",
    "class Relationship(BaseModel):\n",
    "    pass\n",
    "\n",
    "MODELS = [User, Tweet, EventLog, Relationship]\n",
    "\n",
    "class BaseTestCase(unittest.TestCase):\n",
    "    def setup(self):\n",
    "        test_db.bind(# 3个参数\n",
    "            MODELS,  # 准备绑定的Models\n",
    "            bind_refs=False,  # 绑定引用的模型\n",
    "            bind_backrefs=False) # 绑定反向引用的模型\n",
    "        test_db.connect() \n",
    "        test_db.create_tables(MODELS)\n",
    "\n",
    "    def tearDown(self):\n",
    "        test_db.drop_tables(MODELS)\n",
    "        test_db.close()\n",
    "\n",
    "test_db.bind()\n",
    "\n",
    "x = BaseTestCase()\n",
    "x.setup()\n",
    "x.tearDown()\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 与flask框架完美集成\n",
    "\n",
    "from flask import Flask\n",
    "from peewee import *\n",
    "\n",
    "database = SqliteDatabase('my_app.db')\n",
    "app = Flask(__name__)\n",
    "\n",
    "# This hook ensures that a connection is opened to handle any queries\n",
    "# generated by the request.\n",
    "@app.before_request\n",
    "def _db_connect():\n",
    "    database.connect()\n",
    "\n",
    "# This hook ensures that the connection is closed when we've finished\n",
    "# processing the request.\n",
    "@app.teardown_request\n",
    "def _db_close(exc):\n",
    "    if not database.is_closed():\n",
    "        database.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "hi yasoob\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "装饰器知识复习\n",
    "'''\n",
    "\n",
    "def hi(name = 'yasoob'):\n",
    "    return 'hi ' + name\n",
    "\n",
    "print(hi())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "hi yasoob\n"
     ]
    }
   ],
   "source": [
    "# greet = hi\n",
    "print(greet())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "output_type": "error",
     "ename": "NameError",
     "evalue": "name 'hi' is not defined",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-8-56d391238a20>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;32mdel\u001b[0m \u001b[0mhi\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mhi\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m: name 'hi' is not defined"
     ]
    }
   ],
   "source": [
    "del hi\n",
    "print(hi())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "hi yasoob\n"
     ]
    }
   ],
   "source": [
    "print(greet())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "<function hi.<locals>.greet at 0x000001EA5CD6B550>\nnow you are in the greet() function\n"
     ]
    }
   ],
   "source": [
    "def hi(name=\"yasoob\"):\n",
    "    def greet():\n",
    "        return \"now you are in the greet() function\"\n",
    "\n",
    "    def welcome():\n",
    "        return \"now you are in the welcome() function\"\n",
    "\n",
    "    if name == \"yasoob\":\n",
    "        return greet\n",
    "    else:\n",
    "        return welcome\n",
    "\n",
    "a = hi()\n",
    "print(a)\n",
    "print(a())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "xxxx\nhi yasoob!\n"
     ]
    }
   ],
   "source": [
    "def hi():\n",
    "    return 'hi yasoob!'\n",
    "\n",
    "def do(func):\n",
    "    print('xxxx')\n",
    "    print(func())\n",
    "\n",
    "do(hi)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "now you are inside the hi()\nin greet()\nin welcome()\nin hi()\n"
     ]
    },
    {
     "output_type": "error",
     "ename": "NameError",
     "evalue": "name 'welcome' is not defined",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-17-e66914a83ce4>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     15\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     16\u001b[0m \u001b[0mgreet\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 17\u001b[1;33m \u001b[0mwelcome\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m: name 'welcome' is not defined"
     ]
    }
   ],
   "source": [
    "def hi(name = 'yasoob'):\n",
    "    print('now you are inside the hi()')\n",
    "\n",
    "    def greet():\n",
    "        return 'in greet()'\n",
    "\n",
    "    def welcome():\n",
    "        return 'in welcome()'\n",
    "\n",
    "    print(greet())\n",
    "    print(welcome())\n",
    "    print('in hi()')\n",
    "\n",
    "hi()\n",
    "\n",
    "greet()\n",
    "welcome()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "我就是那个被装饰的函数\n前a_func()\n我就是那个被装饰的函数\na_func后\n"
     ]
    }
   ],
   "source": [
    "def a_new_decorator(a_func):\n",
    "\n",
    "    def warpTheFunction():\n",
    "        print('前a_func()')\n",
    "\n",
    "        a_func()\n",
    "\n",
    "        print('a_func后')\n",
    "    \n",
    "    return warpTheFunction\n",
    "\n",
    "\n",
    "def a_func_requiring_decoration():\n",
    "    print('我就是那个被装饰的函数')\n",
    "\n",
    "\n",
    "\n",
    "a_func_requiring_decoration()\n",
    "\n",
    "a_func_requiring_decoration = a_new_decorator(a_func_requiring_decoration)\n",
    "\n",
    "a_func_requiring_decoration()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "前a_func()\n我是另外一个被装饰的函数\na_func后\n"
     ]
    }
   ],
   "source": [
    "@a_new_decorator\n",
    "def another_func():\n",
    "    \"\"\"Hey you! Decorate me\"\"\"\n",
    "    print('我是另外一个被装饰的函数')\n",
    "\n",
    "another_func()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "None\nwarpTheFunction\n"
     ]
    }
   ],
   "source": [
    "print(another_func.__doc__)\n",
    "print(another_func.__name__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "another_func\nHey you! Decorate me\n"
     ]
    }
   ],
   "source": [
    "from functools import wraps\n",
    "\n",
    "def a_new_decorator(a_func):\n",
    "    @wraps(a_func)\n",
    "    def warpTheFunction():\n",
    "        print('前')\n",
    "        a_func()\n",
    "        print('后')\n",
    "\n",
    "    return warpTheFunction\n",
    "\n",
    "@a_new_decorator\n",
    "def another_func():\n",
    "    \"\"\"Hey you! Decorate me\"\"\"\n",
    "    print('我是另外一个被装饰的函数')\n",
    "\n",
    "print(another_func.__name__)\n",
    "print(another_func.__doc__)\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "'Function is running'"
      ]
     },
     "metadata": {},
     "execution_count": 29
    }
   ],
   "source": [
    "# 装饰器的标准写法\n",
    "\n",
    "from functools import wraps\n",
    "\n",
    "def decorator(f):\n",
    "    @wraps(f)\n",
    "    def decorated(*args, **kwargs):\n",
    "        if not can_run:\n",
    "            return \"Function will not run\"\n",
    "        return f(*args, **kwargs)\n",
    "    return decorated\n",
    "\n",
    "@decorator\n",
    "def func():\n",
    "    return \"Function is running\"\n",
    "\n",
    "can_run = True\n",
    "func()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "'Function will not run'"
      ]
     },
     "metadata": {},
     "execution_count": 30
    }
   ],
   "source": [
    "can_run = False\n",
    "func()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "func\n<method-wrapper '__getattribute__' of function object at 0x000001EA5DB5D310>\n"
     ]
    }
   ],
   "source": [
    "print(func.__name__)\n",
    "print(func.__getattribute__)\n",
    "# print(func.___)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "# flask 授权场景\n",
    "\n",
    "from functools import wraps\n",
    "\n",
    "def requires_auth(f):\n",
    "    @warps(f)\n",
    "    def decorated(*args, **kwargs):\n",
    "        auth = request.authorization\n",
    "        if not auth or not chech_auth(auth.name, auth.password):\n",
    "            authenticate()\n",
    "        return f(*args, **kwargs)\n",
    "    return decorated\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "a_func_requiring_decoration was called\n我就是那个被装饰的函数\n"
     ]
    }
   ],
   "source": [
    "# 日志装饰\n",
    "\n",
    "from functools import wraps\n",
    "\n",
    "def logit(func):\n",
    "    @wraps(func)\n",
    "    def with_logging(*args, **kwargs):\n",
    "        print(func.__name__ + ' was called')\n",
    "        return func(*args, **kwargs)\n",
    "        \n",
    "    return with_logging\n",
    "\n",
    "@logit\n",
    "def a_func_requiring_decoration():\n",
    "    print('我就是那个被装饰的函数')\n",
    "\n",
    "a_func_requiring_decoration()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "func1 was called\nfunc2 was called\n"
     ]
    }
   ],
   "source": [
    "from functools import wraps\n",
    "\n",
    "def logit(logfile = 'out.log'):\n",
    "    def logging_decorator(func):\n",
    "        @wraps(func)\n",
    "        def wrapped_function(*args, **kwargs):\n",
    "            log_str = func.__name__ + ' was called'\n",
    "            print(log_str)\n",
    "            with open(logfile, 'a') as open_file:\n",
    "                open_file.write(log_str +'\\n')\n",
    "            return func(*args, **kwargs)\n",
    "        return wrapped_function\n",
    "    return logging_decorator\n",
    "\n",
    "@logit()\n",
    "def func1():\n",
    "    pass\n",
    "\n",
    "@logit(logfile='func2.log')\n",
    "def func2():\n",
    "    pass\n",
    "\n",
    "func1()\n",
    "func2()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "myfunc1 was called\n"
     ]
    }
   ],
   "source": [
    "\n",
    "from functools import wraps\n",
    "\n",
    "class logit(object):\n",
    "    def __init__(self, logfile = 'out.log'):\n",
    "        self.logfile = logfile\n",
    "\n",
    "    def __call__(self, func):\n",
    "        @wraps(func)\n",
    "        def wrapped_function(*args, **kwargs):\n",
    "            log_str = func.__name__ +' was called'\n",
    "            print(log_str)\n",
    "            with open(self.logfile, 'a') as open_file:\n",
    "                open_file.write(log_str + '\\n')\n",
    "            self.notify()\n",
    "            return func(*args, **kwargs)\n",
    "        return wrapped_function\n",
    "\n",
    "    def notify(self):\n",
    "        pass\n",
    "\n",
    "@logit()\n",
    "def myfunc1():\n",
    "    pass\n",
    "\n",
    "myfunc1()\n",
    "\n",
    "class email_logit(logit):\n",
    "    def __init__(self, email = 'admin@project.com', *args, **kwargs):\n",
    "        self.email = email\n",
    "        super(email_logit, self).__init(*args, **kwargs)\n",
    "\n",
    "    def notify(self):\n",
    "\n",
    "        pass\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ]
}